﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using Bonjour;
using System.Net.Sockets;
using System.Net;

namespace OfficeWorkstation
{
    public partial class MainForm : Form
    {
        private String m_name;
        private const int BUFFER_SIZE = 1024;

        private Bonjour.DNSSDEventManager m_eventManager = null;
        private Bonjour.DNSSDService m_service = null;
        private Bonjour.DNSSDService m_registrar = null;
        private Bonjour.DNSSDService m_browser = null;
        private Bonjour.DNSSDService m_resolver = null;
        private Socket m_socket = null;

        public byte[] m_buffer = new byte[BUFFER_SIZE];
        private StringBuilder m_sb = new StringBuilder(1024);
        delegate void ReadMessageCallback(String data);
        ReadMessageCallback m_readMessageCallback;

        public MainForm()
        {
            InitializeComponent();

            try
            {
                m_service = new DNSSDService();
            }
            catch
            {
                MessageBox.Show("Bonjour service is not available");
                Application.Exit();
            }

            m_eventManager = new DNSSDEventManager();
            m_eventManager.ServiceRegistered += new _IDNSSDEvents_ServiceRegisteredEventHandler(this.ServiceRegistered);

            /*
            m_eventManager.ServiceFound += new _IDNSSDEvents_ServiceFoundEventHandler(this.ServiceFound);
            m_eventManager.ServiceLost += new _IDNSSDEvents_ServiceLostEventHandler(this.ServiceLost);
            m_eventManager.ServiceResolved += new _IDNSSDEvents_ServiceResolvedEventHandler(this.ServiceResolved);

            m_eventManager.QueryRecordAnswered += new _IDNSSDEvents_QueryRecordAnsweredEventHandler(this.QueryAnswered);
            m_eventManager.OperationFailed += new _IDNSSDEvents_OperationFailedEventHandler(this.OperationFailed);
             */ 

            m_readMessageCallback = new ReadMessageCallback(OnReadMessage);

        }
        public void ServiceRegistered
                            (
                            DNSSDService service,
                            DNSSDFlags flags,
                            String name,
                            String regType,
                            String domain
                            )
        {
            m_name = name;

            try
            {
                m_browser = m_service.Browse(0, 0, "_ims._udp", null, m_eventManager);
            }
            catch
            {
                MessageBox.Show("Browse Failed", "Error");
                Application.Exit();
            }
        }       

        private void OnReadMessage(String msg)
        {
            int rgb = 0;

            for (int i = 0; i < msg.Length && msg[i] != ':'; i++)
            {
                rgb = rgb ^ ((int)msg[i] << (i % 3 + 2) * 8);
            }

            Color color = Color.FromArgb(rgb & 0x007F7FFF);
            txtMessageBox.AppendText(msg + Environment.NewLine);
            //richTextBox1.SelectionColor = color;
            //richTextBox1.AppendText(msg + Environment.NewLine);
        }

        //
        // OnReadSocket
        //
        // Called by the .NET core when there is data to be read on a socket
        //
        // This is called from a worker thread by the .NET core
        //
        private void OnReadSocket(IAsyncResult ar)
        {
            try
            {
                int read = m_socket.EndReceive(ar);

                if (read > 0)
                {
                    String msg = Encoding.UTF8.GetString(m_buffer, 0, read);

                    Invoke(m_readMessageCallback, new Object[] { msg });
                }

                m_socket.BeginReceive(m_buffer, 0, BUFFER_SIZE, 0, new AsyncCallback(OnReadSocket), this);
            }
            catch
            {
            }
        }

        private void MainForm_Load(object sender, EventArgs e)
        {
            IPEndPoint localEP = new IPEndPoint(System.Net.IPAddress.Any, 0);
            //
            // create the socket and bind to INADDR_ANY
            //
            m_socket = new Socket(AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp);
            //m_socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
            m_socket.Bind(localEP);
            localEP = (IPEndPoint)m_socket.LocalEndPoint;

            //
            // start asynchronous read
            //
            m_socket.BeginReceive(m_buffer, 0, BUFFER_SIZE, 0, new AsyncCallback(this.OnReadSocket), this);
            try
            {
                //
                // start the register and browse operations
                //
                m_registrar = m_service.Register(0, 0, System.Environment.UserName, "_ims._udp", null, null, (ushort)localEP.Port, null, m_eventManager);
            }
            catch
            {
                MessageBox.Show("Bonjour service is not available", "Error");
                Application.Exit();
            }
            /*
            ListViewItem temp = new ListViewItem();
            temp.Text = "This heere";
                        

            
            Object x = txtMessageBox.Items[1];            
             */
        }


        protected override void Dispose(bool disposing)
        {
            if (disposing)
            {
                if (components != null)
                {
                    components.Dispose();
                }

                if (m_registrar != null)
                {
                    m_registrar.Stop();
                }

                if (m_browser != null)
                {
                    m_browser.Stop();
                }

                if (m_resolver != null)
                {
                    m_resolver.Stop();
                }

                //m_eventManager.ServiceFound -= new _IDNSSDEvents_ServiceFoundEventHandler(this.ServiceFound);
                //m_eventManager.ServiceLost -= new _IDNSSDEvents_ServiceLostEventHandler(this.ServiceLost);
                //m_eventManager.ServiceResolved -= new _IDNSSDEvents_ServiceResolvedEventHandler(this.ServiceResolved);
                //m_eventManager.QueryRecordAnswered -= new _IDNSSDEvents_QueryRecordAnsweredEventHandler(this.QueryAnswered);
                //m_eventManager.OperationFailed -= new _IDNSSDEvents_OperationFailedEventHandler(this.OperationFailed);
            }
            base.Dispose(disposing);
        }

        /*

        private void txtMessageBox_SelectedIndexChanged(object sender, EventArgs e)
        {
            PeerData peer = (PeerData)txtMessageBox.SelectedItem;

            try
            {
                m_resolver = m_service.Resolve(0, peer.InterfaceIndex, peer.Name, peer.Type, peer.Domain, m_eventManager);
            }
            catch
            {
                MessageBox.Show("Unable to Resolve service", "Error");
                Application.Exit();
            }

        }
         */


        public delegate void AddMessageDelegate(String text, bool messageBox);

        public void addMessage(String str, bool messageBox)
        {
            if (this.txtMessageBox.InvokeRequired)
            {
                // This is a worker thread so delegate the task.
                this.txtMessageBox.Invoke(new AddMessageDelegate(this.addMessage), new object[] { str, messageBox });
            }
            else
            {
                if (!messageBox)
                    txtMessageBox.Text += str + " \r\n";
                else
                    MessageBox.Show(str);
            }
        }

    }
}
